package Linux五种IO模型.reactor1;

import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.SocketChannel;

/**
 * @author coderFu
 * @create 2022/3/6
 * 内容的读写
 */
public class HandleDemo implements Runnable{

    private final  SelectionKey key;

    private final SocketChannel socketChannel;

    int state;

    public HandleDemo(SelectionKey key,SocketChannel socketChannel){
        this.key = key;
        this.socketChannel = socketChannel;
        // 初始化的状态设置为Reading 可以读取
        state = 0 ;
    }

    @Override
    public void run() {

        try{
            // 先进行读，然后再对客户端进行应答
            if (state == 0){
                read();
            }else {
                send();
            }
        }catch (Exception e){
            e.printStackTrace();
            // 发生错误，关闭连接
            closeChannel();
        }
    }


    public void read() throws IOException {

        // 将缓冲区中的数据读取到数组中
        byte[] arr = new byte[1024];
        // 将此缓冲区中的数据和数组建立联系
        ByteBuffer buffer = ByteBuffer.wrap(arr);

        // 将数据读取到buffer中，其实也在arr中
        int read = socketChannel.read(buffer);

        if(read == -1){
            System.out.println("说明数据读取完毕");
            closeChannel();
            return;
        }

        // 将读取到的byte数据 转换为字符串类型
        String str = new String(arr);

        if (!"".equals(str)){
            // 模拟逻辑处理
            process();

            System.out.println("获取地址和传输的值"+str);

            // 读取完毕，修改状态，将结果发生给客户端
            state = 1;
            // 下一次使用该管道就是写数据
            key.interestOps(SelectionKey.OP_WRITE);


        }
    }

    public void send() throws IOException {

        String str = "模拟向客户端发送响应数据"+socketChannel.socket().getRemoteSocketAddress().toString();

        ByteBuffer byteBuffer = ByteBuffer.wrap(str.getBytes());

        while (byteBuffer.hasRemaining()){
            // 回传client 字符串，发送buf的position 位置到limit 位置之间的内容

            socketChannel.write(byteBuffer);

            state = 0;
            // 改变 key 的 感兴趣事件
            key.interestOps(SelectionKey.OP_READ);

        }








    }

    public void process(){
        try {
           Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    public void closeChannel(){

        try{
            socketChannel.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
